package com.znjc.iot.service.impl;

import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.znjc.iot.domain.DeviceCommand;
import com.znjc.iot.domain.DeviceType;
import com.znjc.iot.domain.IotDataVO;
import com.znjc.iot.domain.IotTypeVO;
import com.znjc.iot.exception.SendDataToSerialPortFailure;
import com.znjc.iot.exception.SerialPortOutputStreamCloseFailure;
import com.znjc.iot.serial.SerialPortUtil;
import com.znjc.iot.service.IotService;
import com.znjc.iot.task.CollectDataTask;
import com.znjc.iot.task.ScheduleManager;
import com.znjc.iot.util.CRC_16;
import com.znjc.iot.util.CommonUtil;
import com.znjc.iot.util.DataUtil;
import com.znjc.iot.util.DateUtil;
import com.znjc.iot.websocket.CustomizedWebSocketClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.nio.channels.NotYetConnectedException;
import java.sql.Timestamp;
import java.util.List;

@Service
@Slf4j
public class IotServiceImpl implements IotService {
    @Value("${znjc.clientId}")
    private String clientId;
    @Autowired
    private CustomizedWebSocketClient socketClient;
    @Autowired
    private ScheduleManager scheduleManager;

    @Override
    public void saveMasterData(IotDataVO dataVO) {
        socketClient.send(packMsg("vue_msg", dataVO.getDeptName() + "命令开始配置").toJSONString());
        CommonUtil.deptName = dataVO.getDeptName();
        if (null != dataVO) {
            //命令集合不为空，发送命令
            if (CollectionUtils.isNotEmpty(dataVO.getCommands())){
                SerialPortUtil serialPortUtil = CommonUtil.getSerialPortUtils(dataVO.getSerial());
                CommonUtil.setFlag = true;
                dataVO.getCommands().forEach(deviceCommand->{
                    socketClient.send(packMsg("vue_msg", deviceCommand.getName()).toJSONString());
                    while (CommonUtil.setFlag){
                        CommonUtil.setFlag = false;
                        CommonUtil.commandId = deviceCommand.getId();
                        try {
                            byte[] byteMsg = CRC_16.getSendBuf(deviceCommand.getCommand().replaceAll(" ",""));
                            serialPortUtil.sendCommand(byteMsg);
                        } catch (SendDataToSerialPortFailure e) {
                            throw new RuntimeException(e);
                        } catch (SerialPortOutputStreamCloseFailure e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
            }
            socketClient.send(packMsg("vue_msg", dataVO.getDeptName() + "命令配置完成").toJSONString());
        }
    }

    @Override
    public void openFlag(IotTypeVO iotTypeVO) {
        if (null == iotTypeVO) {
            return;
        }
        if (0 == iotTypeVO.getOpenFlag()) {
            if (null == iotTypeVO.getCronFlag()) {
                //根据参数初始化采集任务
                CollectDataTask task = new CollectDataTask(iotTypeVO.getSerial().getId(), socketClient, iotTypeVO.getSerial(), iotTypeVO.getDataChecks());
                //启动定时任务
                scheduleManager.startTask(task, iotTypeVO.getSerial().getGatherTime());
                socketClient.send(packMsg("vue_msg", "已开始采集！").toJSONString());
            } else {
                //修改采集时间
                scheduleManager.changeTask(iotTypeVO.getSerial().getId(), iotTypeVO.getSerial().getGatherTime());
                socketClient.send(packMsg("vue_msg", "已开始采集！").toJSONString());
            }
        } else {
            //关闭采集
            scheduleManager.stopTask(iotTypeVO.getSerial().getId());
            socketClient.send(packMsg("vue_msg", "已关闭采集！").toJSONString());
        }
    }

    @Override
    public void analyzeData(String needData, Timestamp date) {
        JSONObject data = new JSONObject();
        data.put("needData", needData);
        data.put("clientName", CommonUtil.deptName);
        data.put("clientId", clientId);
        data.put("date", DateUtil.timestampConvertString(date));
        if(null != CommonUtil.commandId && (CommonUtil.commandId.intValue() > 0 || CommonUtil.commandId.intValue() == -1)){
            //打开命令设置开关
            CommonUtil.setFlag = true;
            data.put("commandId", CommonUtil.commandId);
            CommonUtil.commandId = 0L;
        }
        try {
            socketClient.send(data.toJSONString());
        } catch (NotYetConnectedException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void closePort(String coms) {
        String[] parts = coms.split("，");
        if(parts.length > 0){
            for(String part : parts){
                if(CommonUtil.protUtils.containsKey(part)){
                    CommonUtil.protUtils.get(part).closePort();
                    socketClient.send(packMsg("vue_msg", "已关闭串口！").toJSONString());
                }
            }
        }

    }

    @Override
    public void taskCommand(String command) {
        if(CollectionUtils.isNotEmpty(CommonUtil.protUtils)){
            for(SerialPortUtil serialPortUtil : CommonUtil.protUtils.values()){
                if(null != serialPortUtil){
                    try {
                        byte[] byteMsg = CRC_16.getSendBuf(command.replaceAll(" ",""));
                        serialPortUtil.sendCommand(byteMsg);
                    } catch (SendDataToSerialPortFailure e) {
                        throw new RuntimeException(e);
                    } catch (SerialPortOutputStreamCloseFailure e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }

    private JSONObject packMsg(String key, String value) {
        JSONObject msg = new JSONObject();
        msg.put(key, value);
        return msg;
    }
}
